public class BioharnessSensor implements ISensor {


	protected static final int HRV = 0;
	private final int RtoR_MSG_ID = 0x24;
	private final int HEART_RATE = 0x100;
	private final int RESPIRATION_RATE = 0x101;
	private final int SKIN_TEMPERATURE = 0x102;
	private final int POSTURE = 0x103;
	private final int PEAK_ACCLERATION = 0x104;

	// Bioharness Framework

	String TAG = "BioHarness Sensor";


	// Bluetooth variables
	BluetoothAdapter adapter = null;
	BTClient _bt;
	ZephyrProtocol _protocol;
	NewConnectedListener _NConnListener;
	boolean connected = false;
	static boolean writeable = false;

	private ConnectThread mConnectThread;
	//private ConnectedThread mConnectedThread;
	private int mState;

	ArrayList<Double> respRates = new ArrayList<Double>();
	ArrayList<Double> skinTemps = new ArrayList<Double>();
	static ArrayList<Double> heartRates = new ArrayList<Double>();
	ArrayList<Double> hrvs = new ArrayList<Double>();
	ArrayList<Double> bhGSRs = new ArrayList<Double>();

	double respRate = 0.0;
	double skinTemp = 0.0;
	double heartRate = 0.0;
	double hrv = 0.0;
	public UUID mSPP_UID;
	public BluetoothSocket mmSocket;

	public BioharnessSensor(BluetoothAdapter b_adapter, BTClient b_bt) {
		adapter = b_adapter;
		_bt = b_bt;

	}
	
	/*private class Connect extends AsyncTask<String, Void, String> {

		@Override
		protected String doInBackground(String... params) {
			String text = "Connection attempted...\n";

			Looper.prepare();

			// setting up Bluetooth connection
			IntentFilter filter = new IntentFilter("android.bluetooth.device.action.PAIRING_REQUEST");
			getApplicationContext().registerReceiver(new BTBroadcastReceiver(), filter);
			IntentFilter filter2 = new IntentFilter("android.bluetooth.device.action.BOND_STATE_CHANGED");
			getApplicationContext().registerReceiver(new BTBondReciever(), filter2);

			String BhMacID = "00:07:80:9D:8A:E8";
			adapter = BluetoothAdapter.getDefaultAdapter();
			Set<BluetoothDevice> pairedDevices = adapter.getBondedDevices();


			// For Zephyr Bioharness
			if (pairedDevices.size() > 0) {
				for (BluetoothDevice device : pairedDevices) {
					if (device.getName().startsWith("BH")) {
						BluetoothDevice btDevice = device;
						BhMacID = btDevice.getAddress();
						break;
					}
				}

				_bt = new BTClient(adapter, BhMacID);
				_NConnListener = new NewConnectedListener(DataHandler,DataHandler);
				_bt.addConnectedEventListener(_NConnListener);

				if(_bt.IsConnected()) {
					// starting Bluetooth connection
					_bt.start();

					Log.i(TAG, "Zephyr Connected");

					connected = true;
				}
				else {
					// exit if connection fails
					Log.w("BlueTooth Connection Failed", "The bluetooth connection failed");

					Log.i(TAG, "Zephyr not connected");

					connected = false;
				}
			}
			return text;
		}

		@Override
		protected void onPostExecute(String result) {

		}

		@Override
		protected void onPreExecute() {

		}

		@Override
		protected void onProgressUpdate(Void... values) {

		}
	}

	private class Disconnect extends AsyncTask<String, Void, String> {

		@Override
		protected String doInBackground(String... params) {
			if(connected){
				//Disconnect sensor
				//Disconnect listener from recieved messages
				_bt.removeConnectedEventListener(_NConnListener);
				//Close the connection to device
				_bt.Close();

				connected = false;
			}

			Log.i(TAG, "Devices Disconnected");
			return "Disconnect attempted...";
		}

		@Override
		protected void onPostExecute(String result){

		}

		@Override
		protected void onPreExecute() {

		}

		@Override
		protected void onProgressUpdate(Void... values){

		}
	}
	 */

	private class Connect extends Thread {
		//public final BluetoothSocket mmsocket;
		private final BluetoothDevice mmDevice;

		public Connect(BluetoothDevice device) {
			mmDevice = device;
			BluetoothSocket tmp = null;

			try{
				tmp = device.createRfcommSocketToServiceRecord(mSPP_UID);
			} catch (IOException e) {}
						mmSocket = tmp;
		}

		public void run() {
			// setting up Bluetooth connection
			IntentFilter filter = new IntentFilter("android.bluetooth.device.action.PAIRING_REQUEST");
			//			getApplicationContext().registerReceiver(new BTBroadcastReceiver(), filter);						************
			IntentFilter filter2 = new IntentFilter("android.bluetooth.device.action.BOND_STATE_CHANGED");
			//			getApplicationContext().registerReceiver(new BTBondReciever(), filter2);							*************

			String BhMacID = "00:07:80:9D:8A:E8";
			Set<BluetoothDevice> pairedDevices = adapter.getBondedDevices();

			// For Zephyr Bioharness
			if (pairedDevices.size() > 0) {
				for (BluetoothDevice device : pairedDevices) {
					if (device.getName().startsWith("BH")) {
						BluetoothDevice btDevice = device;
						BhMacID = btDevice.getAddress();
						break;
					}
				}

				_bt = new BTClient(adapter, BhMacID);
				_NConnListener = new NewConnectedListener(DataHandler,DataHandler);
				_bt.addConnectedEventListener(_NConnListener);

				if(_bt.IsConnected()) {
					// starting Bluetooth connection
					_bt.start();

					Log.i(TAG, "Zephyr Connected");

					connected = true;
				}
				else {
					// exit if connection fails
					Log.w("BlueTooth Connection Failed", "The bluetooth connection failed");

					Log.i(TAG, "Zephyr not connected");

					connected = false;
				}
			}






			
			/*setName("Bioharness ConnectThread");

			mAdapter.cancelDiscovery();

			try{
				mmSocket.connect();
			} catch (IOException connectException) {
				connectionFailed();

				try{
					mmSocket.close();
				} catch (IOException closeException) {}
				return;
			}

			synchronized (BioharnessSensor.this) {
				mConnectThread = null;
			}

			connected(mmSocket, mmDevice);
			 */







		}

		public void cancel() {
			//					mmSocket.close();										*******************
		}
	}

	/*private class Disconnect {
		if(connected){
			//Disconnect sensor
			//Disconnect listener from recieved messages
			_bt.removeConnectedEventListener(_NConnListener);
			//Close the connection to device
			_bt.Close();
	
			connected = false;
		}
	
		Log.i(TAG, "Devices Disconnected");
		return "Disconnect attempted...";
	}*/


	private class BTBondReciever extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			Bundle b = intent.getExtras();
			BluetoothDevice device = adapter.getRemoteDevice(b.get("android.bluetooth.device.extra.DEVICE").toString());
			Log.d("Bond state", "BOND_STATED = " + device.getBondState());
		}
	}

	private class BTBroadcastReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			Log.d("BTIntent", intent.getAction());
			Bundle b = intent.getExtras();
			Log.d("BTIntent", b.get("android.bluetooth.device.extra.DEVICE").toString());
			Log.d("BTIntent", b.get("android.bluetooth.device.extra.PAIRING_VARIANT").toString());
			try {
				BluetoothDevice device = adapter.getRemoteDevice(b.get("android.bluetooth.device.extra.DEVICE").toString());
				Method m = BluetoothDevice.class.getMethod("convertPinToBytes", new Class[] {String.class} );
				byte[] pin = (byte[])m.invoke(device, "1234");
				m = device.getClass().getMethod("setPin", new Class [] {pin.getClass()});
				Object result = m.invoke(device, pin);
				Log.d("BTTest", result.toString());
			} catch (SecurityException e1) {
				e1.printStackTrace();
			} catch (NoSuchMethodException e1) {
				e1.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}
	}

	final Handler DataHandler = new Handler() {
		double data = 0.0;
		public void handleMessage(Message msg) {
			switch(msg.what){
			case RESPIRATION_RATE:
				respRate = getRespRate(msg);
				break;
			case SKIN_TEMPERATURE:
				skinTemp = getSkinTemp(msg);
				break;
			case HEART_RATE:
				heartRate = getHeartRate(msg);
				break;
			case HRV:
				hrv = getHRV(msg);
				break;
			default:
				break;
			}
		}
	};

	private double getRespRate(Message msg) {
		double rate = 0.0;

		rate = (double) msg.getData().getFloat("RespirationRate");
		if(writeable) respRates.add(rate);

		return rate;
	}

	private double getSkinTemp(Message msg) {
		double temp = 0.0;

		temp = (double) msg.getData().getFloat("SkinTemperature");
		if(writeable) skinTemps.add(temp);

		return temp;
	}

	private double getHeartRate(Message msg){
		double heartRate = 0.0;

		heartRate = (double) msg.getData().getInt("HeartRate");
		if(writeable) heartRates.add(heartRate);

		return heartRate;
	}

	private double getHRV(Message msg) {
		double hrv = 0.0;

		hrv = (double) msg.getData().getInt("RMSSD");
		if(writeable) hrvs.add(hrv);

		return hrv;
	}

	private double getGSR(Message msg) {
		double gsr = 0.0;

		gsr = (double) msg.getData().getInt("GSR");
		if(writeable) bhGSRs.add(gsr);


		return gsr;
	}

	public static double getRawData(String dataName, Message msg) throws IllegalArgumentException{

		double data = 0.0;

		if(dataName.equals("Respiration Rate")){ data = getRespRate(msg); }
		else if(dataName.equals("Skin Temperature")){ data = getSkinTemp(msg); }
		else if(dataName.equals("Heart Rate")){ data = getHeartRate(msg); }
		else if(dataName.equals("HRV")){ data = getHRV(msg); }
		else if(dataName.equals("GSR")){ data = getGSR(msg); }
		else throw new IllegalArgumentException("Error 404: Sensor not found");

		return data;
	}

	public int getAdjustedData(String[] sensorNames) throws IllegalArgumentException{
		int stressLevel = 0;

		// TODO: Determine stress calculations and how multiple interact

		// For each sensor in sensorNames, perform stress calculation using that sensor's data

		//throw new IllegalArgumentException("Error 404: Sensor not found");

		return stressLevel;
	}

	public String[] getSensorList(){
		String[] sensors = {"Respiration Rate","Skin Temperature", "Heart Rate", "HRV", "GSR"};	

		return sensors;
	}

	@Override
	public void connect() {
		// TODO Auto-generated method stub
		Connect connection = new Connect(null);


	}

	@Override
	public void disconnect() {
		// TODO Auto-generated method stub
		if(connected){
			//Disconnect sensor
			//Disconnect listener from received messages
			_bt.removeConnectedEventListener(_NConnListener);
			//Close the connection to device
			_bt.Close();

			connected = false;
		}

		Log.i(TAG, "Devices Disconnected");
	}

	@Override
	public double getRawData(String sensorName)
			throws IllegalArgumentException {
		// TODO Auto-generated method stub
		return 0;
	}

}

